﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows;
using System.Collections.Specialized;
using System.Xml;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace Particles
{
   

    public partial class Form1 : Form
    {
        public Emitter emit = new Emitter();
        public Particle part = new Particle();

        
        Rectangle emittersetSize = new Rectangle(200, 200, 10, 10);
        PointF emitterSetstartVeloctiy = new PointF(2.0f, 2.0f);
        PointF emitterSetEndVelocity = new PointF(2.0f, 2.0f);
        float emitterSetAngel = 90.0f;
        Particle[] SetEmittingparticles = new Particle[400];
        Point Setvariation = new Point(0, 0);
        int SetMaxPart = 1000;
        List<Particle> SetList = new List<Particle>();
        List<Particle> deadList = new List<Particle>();

        static int previoussecond = 0;
        static int FrameRate = 0;
        static int previousTime = 0;
        string texture;
        string path;

        public bool Looping;

        public bool parttexture;
        

        public Form1()
        {
            FolderBrowserDialog relative = new FolderBrowserDialog();
            if (DialogResult.OK == relative.ShowDialog())
            {
                path = relative.SelectedPath;
            }

            InitializeComponent();

            
            ManagedDirect3D.Instance.InitManagedDirect3D(panel1, true);
            ManagedTextureManager.Instance.InitManagedTextureManager(ManagedDirect3D.Instance.Device, ManagedDirect3D.Instance.Sprite);

            emit.Emitrect = emittersetSize;
            emit.RectVelocity = emitterSetstartVeloctiy;
            emit.EndrectVelocity = emitterSetEndVelocity;
            emit.EmitAngel = emitterSetAngel;
            emit.NumParticles = SetEmittingparticles;
            emit.Positionvariation = Setvariation;
            emit.MaxParticles = SetMaxPart;
            emit.LiveParticles = SetList;
            emit.DeadParticles = deadList;
            emit.DelayTimer = DateTime.Now.Millisecond;



            if (emit.LiveParticles.Count < emit.MaxParticles)
            {
                part.ResetParticle(emit);
                emit.LiveParticles.Add(part);
            }

            Point SetPartPosition = new Point(emittersetSize.X, emittersetSize.Y);

            part.PartPosition = SetPartPosition;

            part.PartColor = new Color();

            numericUpDown1.Value = emittersetSize.Width;
            numericUpDown2.Value = emittersetSize.Height;
            numericUpDown3.Value = emittersetSize.X;
            numericUpDown4.Value = emittersetSize.Y;

            numericUpDown5.Value = (decimal)emitterSetstartVeloctiy.X;
            numericUpDown6.Value = (decimal)emitterSetstartVeloctiy.Y;
            numericUpDown7.Value = Setvariation.X;
            numericUpDown8.Value = Setvariation.Y;

            numericUpDown9.Value = (decimal)emitterSetAngel;
            numericUpDown10.Value = SetMaxPart;
            numericUpDown21.Value = (decimal)emitterSetEndVelocity.X;
            numericUpDown22.Value = (decimal)emitterSetEndVelocity.Y;

            numericUpDown11.Value = part.PartScale.X;
            numericUpDown12.Value = part.PartScale.Y;
            numericUpDown13.Value = part.EndpartScale.X;
            numericUpDown14.Value = part.EndpartScale.Y;

            numericUpDown16.Value = part.LifeSpan;
            numericUpDown17.Value = (decimal)part.PartVeloctiy.X;
            numericUpDown18.Value = (decimal)part.PartVeloctiy.Y;
            numericUpDown19.Value = (decimal)part.EndVeloctiy.X;
            numericUpDown20.Value = (decimal)part.EndVeloctiy.Y;

            Looping = true;

            parttexture = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void backgroundColorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog dlg = new ColorDialog();

            dlg.Color = panel1.BackColor;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                panel1.BackColor = dlg.Color;
            }
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void PositionVariationX_ValueChanged(object sender, EventArgs e)
        {

        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            //SolidBrush whiteBrush = new SolidBrush(Color.Black);
            //// Create location and size of rectangle.
            //// Fill rectangle to screen.
            //e.Graphics.FillRectangle(whiteBrush, panel1.Location.X, panel1.Location.Y, panel1.Width, panel1.Height);
            //this.Invalidate();

        }

        private void VelocityX_ValueChanged(object sender, EventArgs e)
        {
            VelocityX.Value = (int)numericUpDown17.Value;
        }

        private void randomizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Randomizer rdm = new Randomizer();

            rdm.Show(this);
        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Looping = false;

            this.Close();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();


            dlg.InitialDirectory = path;
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement xRoot = XElement.Load(dlg.FileName);

                IEnumerable<XElement> emitter = xRoot.Elements("Emitter");

                foreach (XElement xemit in emitter)
                {
                    Emitter em = new Emitter();
                    em.LiveParticles = new List<Particle>();
                    em.Emitrect = new Rectangle((int)xemit.Attribute("PositionX"),
                                                            (int)xemit.Attribute("PositionY"),
                                                            (int)xemit.Attribute("Width"),
                                                            (int)xemit.Attribute("Height"));

                    em.MaxParticles = (int)xemit.Attribute("NumberOfParticles");
                    em.ImageID = (int)xemit.Attribute("Image");
                    em.RectVelocity = new PointF((float)xemit.Attribute("VelocityX"), (float)xemit.Attribute("VelocityY"));
                    em.EndrectVelocity = new PointF((float)xemit.Attribute("EndingVelocityX"), (float)xemit.Attribute("EndingVelocityY"));
                    em.Positionvariation = new Point((int)xemit.Attribute("PositionVariationX"), (int)xemit.Attribute("PositionVariationY"));
                    em.EmitAngel = (int)xemit.Attribute("SpreadAngle");
                    // em.Emitrect.Width = (string)xemit.Attribute("Width");

                    IEnumerable<XElement> xparticle = xRoot.Elements("Particles");

                    foreach (XElement xpart in xparticle)
                    {
                        Particle pt = new Particle();
                        pt.PartScale = new Point((int)xpart.Attribute("ScaleX"), (int)xpart.Attribute("ScaleY"));
                        pt.EndpartScale = new Point((int)xpart.Attribute("EndScaleX"), (int)xpart.Attribute("EndScaleY"));
                        pt.LifeSpan = (int)xpart.Attribute("LifeSpan");
                        pt.PartVeloctiy = new PointF((float)xpart.Attribute("VelocityX"), (float)xpart.Attribute("VeloctiyY"));
                        pt.EndVeloctiy = new PointF((float)xpart.Attribute("EndingVelocityX"), (float)xpart.Attribute("EndingVelocityY"));
                        em.LiveParticles.Add(pt);
                    }
                    emittersetSize = em.Emitrect;
                    emit.ImageID = em.ImageID;
                    SetMaxPart = em.MaxParticles;
                    emitterSetstartVeloctiy = em.RectVelocity;
                    Setvariation = em.Positionvariation;
                    emitterSetAngel = em.EmitAngel;
                }
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();

            sfd.InitialDirectory = path;
            string file = "//Default.xml";
            string temp = "";

            if (DialogResult.OK == sfd.ShowDialog())
            {
                file = sfd.FileName;
                temp += file;

                for (int x = 0; x < file.Length; x++ )
                {
                    if (x > file.Length)
                    {
                        temp += file[x];
                    }
                }

                file += ".xml";

                temp = path;

                temp += file;

                XmlTextWriter towrite = new XmlTextWriter(file, null);

                towrite.WriteStartDocument();

                towrite.WriteStartElement("Root");

                towrite.WriteStartElement("Emitter");

                towrite.WriteAttributeString("PositionX", emittersetSize.X.ToString());
                towrite.WriteAttributeString("PositionY", emittersetSize.Y.ToString());
                towrite.WriteAttributeString("Width", emittersetSize.Width.ToString());
                towrite.WriteAttributeString("Height", emittersetSize.Height.ToString());
                towrite.WriteAttributeString("VelocityX", emitterSetstartVeloctiy.X.ToString());
                towrite.WriteAttributeString("VelocityY", emitterSetstartVeloctiy.Y.ToString());
                towrite.WriteAttributeString("NumberOfParticles", SetMaxPart.ToString());
                towrite.WriteAttributeString("Image", emit.ImageID.ToString());
                towrite.WriteAttributeString("PositionVariationX", Setvariation.X.ToString());
                towrite.WriteAttributeString("PositionVariationY", Setvariation.Y.ToString());
                towrite.WriteAttributeString("SpreadAngle", emitterSetAngel.ToString());
                towrite.WriteAttributeString("EndingVelocityX", emitterSetEndVelocity.X.ToString());
                towrite.WriteAttributeString("EndingVelocityY", emitterSetEndVelocity.Y.ToString());
                towrite.WriteEndElement();

                towrite.WriteStartElement("Particles");

                towrite.WriteAttributeString("ScaleX", part.PartScale.X.ToString());
                towrite.WriteAttributeString("ScaleY", part.PartScale.Y.ToString());
                towrite.WriteAttributeString("EndScaleX", part.EndpartScale.X.ToString());
                towrite.WriteAttributeString("EndScaleY", part.EndpartScale.Y.ToString());
                towrite.WriteAttributeString("LifeSpan", part.LifeSpan.ToString());
                towrite.WriteAttributeString("VelocityX", part.PartVeloctiy.X.ToString());
                towrite.WriteAttributeString("VeloctiyY", part.PartVeloctiy.Y.ToString());
                towrite.WriteAttributeString("EndingVelocityX", part.EndpartScale.X.ToString());
                towrite.WriteAttributeString("EndingVelocityY", part.EndpartScale.Y.ToString());

                towrite.WriteEndElement();

                towrite.WriteEndDocument();

                towrite.Close();
            }
        }

        private void backgroundImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog backImage = new OpenFileDialog();
            backImage.ShowDialog(this);
        }

        private void ParticleImage_Click(object sender, EventArgs e)
        {
            parttexture = false;

            OpenFileDialog LoadParticle = new OpenFileDialog();

            if (DialogResult.OK == LoadParticle.ShowDialog())
            {
                for (int x = 0; x < emit.LiveParticles.Count; x++ )
                {
                    emit.ImageID = ManagedTextureManager.Instance.LoadTexture(LoadParticle.FileName, 0);
                }
                parttexture = true;

            }
        }

        private void StartColor_Click(object sender, EventArgs e)
        {
            Starting_Color sparticleColor = new Starting_Color();

            sparticleColor.ShowDialog(this);
        }

        private void EndingColor_Click(object sender, EventArgs e)
        {
            Ending_Color eparticleColor = new Ending_Color();
            eparticleColor.ShowDialog(this);
        }

        private void EmitWidth_ValueChanged(object sender, EventArgs e)
        {      
            emittersetSize.Width = (int)numericUpDown1.Value;
        }

        private void VelocityXBar_Scroll(object sender, EventArgs e)
        {
            numericUpDown17.Value = VelocityX.Value;
        }

        private void VelocityYBar_Scroll(object sender, EventArgs e)
        {
            numericUpDown18.Value = trackBar2.Value;
        }

        private void VelocityY_ValueChanged(object sender, EventArgs e)
        {
            trackBar2.Value = (int)numericUpDown18.Value;
        }

        private void EndingVelocityXBar_Scroll(object sender, EventArgs e)
        {
            numericUpDown19.Value = trackBar3.Value;
        }

        private void EndingVelocityX_ValueChanged(object sender, EventArgs e)
        {
            trackBar3.Value = (int)numericUpDown19.Value;
        }

        private void EndingVelocityYBar_Scroll(object sender, EventArgs e)
        {
            numericUpDown20.Value = trackBar4.Value;
        }

        private void EndingVelocityY_ValueChanged(object sender, EventArgs e)
        {
            trackBar4.Value = (int)numericUpDown20.Value;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Looping = false;
        }
        private void EmitHeight_ValueChanged(object sender, EventArgs e)
        {
            emittersetSize.Height = (int)numericUpDown2.Value;
        }

        private void EmitPosX_ValueChanged(object sender, EventArgs e)
        {
            emittersetSize.X = (int)numericUpDown3.Value;
        }

        private void EmitPosY_ValueChanged(object sender, EventArgs e)
        {
            emittersetSize.Y = (int)numericUpDown4.Value;
        }

        public void Update()
        {
            int startTime = DateTime.Now.Millisecond;

            emit.Emitrect = emittersetSize;


            if (emit.MaxParticles > 0)
            {
                if (emit.LiveParticles.Count < emit.MaxParticles)
                {
                    part = new Particle();
                    part.ResetParticle(emit);
                    emit.LiveParticles.Add(part);
                }
            }

            if (emit.DeadParticles.Count > 0)
            {
                part = emit.DeadParticles.First<Particle>();
                emit.DeadParticles.Remove(part);
                part.ResetParticle(emit);
            }
            else if (emit.DeadParticles.Count == 0)
            {
                part = new Particle();
                part.ResetParticle(emit);
                emit.LiveParticles.Add(part);

            }

            //part.UpdateParticle(emit);
            for (int x = 0; x < emit.LiveParticles.Count; x++ )
            {
                emit.LiveParticles[x].UpdateParticle(emit);
            }
            //part.UpdateParticle(emit);            
        }


        public void Render()
        {
            ManagedDirect3D.Instance.Clear(0, 0, 0);

            ManagedDirect3D.Instance.DeviceBegin();
            //ManagedDirect3D.Instance.LineBegin();
            ManagedDirect3D.Instance.SpriteBegin();

            ManagedDirect3D.Instance.Sprite.Flush();

            ManagedDirect3D.Instance.Device.RenderState.AlphaBlendEnable = true;

            ManagedDirect3D.Instance.DrawRect(emittersetSize, 0, 255, 255);

            ManagedDirect3D.Instance.DrawText("hello world", 30, 30, 0, 255, 255);

            FrameRate++;


            while (DateTime.Now.Second != previoussecond )
            {
                previoussecond = DateTime.Now.Second;
                FrameRate = 0;
            }

            ManagedDirect3D.Instance.DrawText(FrameRate.ToString(), 150, 150, 0, 255, 255);

            ManagedDirect3D.Instance.DrawText(emit.LiveParticles.Count.ToString(), 50, 50, 0, 255, 255);


            uint nCount = 0;

            for (int x = 0; x < emit.LiveParticles.Count; x++ )
            {

                if (parttexture == true)
                {
                    ManagedTextureManager.Instance.Draw(emit.ImageID, (int)emit.LiveParticles[x].PartPosition.X, (int)emit.LiveParticles[x].PartPosition.Y, 1.0f, 1.0f,Rectangle.Empty, 0, 0, 0.0f, Color.White.ToArgb());
                }
                else
                {
                    emit.LiveParticles[x].DrawParticles();
                }
                nCount++;
            }


             ManagedDirect3D.Instance.DrawText("disp" + nCount.ToString(), 70, 70, 0, 255, 255 );

            //ManagedDirect3D.Instance.LineEnd();
            //////////////////////////////////////////////////////////////////////////
            //// MIGHT HAVE TO ADD CLEAR RIGHT HERE
            //////////////////////////////////////////////////////////////////////////


            ManagedDirect3D.Instance.Device.RenderState.DestinationBlend = emit.Desblend;
            ManagedDirect3D.Instance.Device.RenderState.SourceBlend = emit.SrcBlend;

            ManagedDirect3D.Instance.Sprite.Flush();

            ManagedDirect3D.Instance.Device.RenderState.AlphaBlendEnable = false;

            ManagedDirect3D.Instance.SpriteEnd();
            ManagedDirect3D.Instance.DeviceEnd();
            ManagedDirect3D.Instance.Present();
        }

        private void PositionVariationY_ValueChanged(object sender, EventArgs e)
        {

        }

        private void SpreadAngle_ValueChanged(object sender, EventArgs e)
        {

        }

        private void panel1_MouseClick(object sender, MouseEventArgs e)
        {
            //if (e.Location.X > emit.)
            //{
            //}
        }

        private void comboBox1_SelectionChangeCommitted(object sender, EventArgs e)
        {
            switch (comboBox1.SelectedIndex)
            {
            case 0:
                    {
                        emit.Desblend = Blend.Zero;
                    }
                    break;

            case 1:
                    {
                        emit.Desblend = Blend.One;
                    }
                    break;
            case 2:
                    {
                        emit.Desblend = Blend.SourceColor;
                    }
                    break;

                case 3:
                    {
                        emit.Desblend = Blend.InvSourceColor;
                    }
                    break;

                case 4:
                    {
                        emit.Desblend = Blend.SourceAlpha;
                    }
                    break;

                case 5:
                    {
                        emit.Desblend = Blend.InvSourceAlpha;
                    }
                    break;

                case 6:
                    {
                        emit.Desblend = Blend.DestinationAlpha;
                    }
                    break;

                case 7:
                    {
                        emit.Desblend = Blend.InvDestinationAlpha;
                    }
                    break;

                case 8:
                    {
                        emit.Desblend = Blend.DestinationColor;
                    }
                    break;

                case 9:
                    {
                        emit.Desblend = Blend.InvDestinationColor;
                    }
                    break;

                case 10:
                    {
                        emit.Desblend = Blend.SourceAlphaSat;
                    }
                    break;

                case 11:
                    {
                        emit.Desblend = Blend.BothSourceAlpha;
                    }
                    break;

                case 12:
                    {
                        emit.Desblend = Blend.BothInvSourceAlpha;
                    }
                    break;

                case 13:
                    {
                        emit.Desblend = Blend.BlendFactor;
                    }
                    break;

                case 14:
                    {
                        emit.Desblend = Blend.InvBlendFactor;
                    }
                    break;
            }
        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (comboBox2.SelectedIndex)
            {
                case 0:
                    {
                        emit.SrcBlend = Blend.Zero;
                    }
                    break;

                case 1:
                    {
                        emit.SrcBlend = Blend.One;
                    }
                    break;

                case 2:
                    {
                        emit.SrcBlend = Blend.SourceColor;
                    }
                    break;

                case 3:
                    {
                        emit.SrcBlend = Blend.InvSourceColor;
                    }
                    break;

                case 4:
                    {
                        emit.SrcBlend = Blend.SourceAlpha;
                    }
                    break;

                case 5:
                    {
                        emit.SrcBlend = Blend.InvSourceAlpha;
                    }
                    break;

                case 6:
                    {
                        emit.SrcBlend = Blend.DestinationAlpha;
                    }
                    break;

                case 7:
                    {
                        emit.SrcBlend = Blend.InvDestinationAlpha;
                    }
                    break;

                case 8:
                    {
                        emit.SrcBlend = Blend.DestinationColor;
                    }
                    break;

                case 9:
                    {
                        emit.SrcBlend = Blend.InvDestinationColor;
                    }
                    break;

                case 10:
                    {
                        emit.SrcBlend = Blend.SourceAlphaSat;
                    }
                    break;

                case 11:
                    {
                        emit.SrcBlend = Blend.BothSourceAlpha;
                    }
                    break;

                case 12:
                    {
                        emit.SrcBlend = Blend.BothInvSourceAlpha;
                    }
                    break;

                case 13:
                    {
                        emit.SrcBlend = Blend.BlendFactor;
                    }
                    break;

                case 14:
                    {
                        emit.SrcBlend = Blend.InvBlendFactor;
                    }
                    break;
            }
            
        }

        private void numericUpDown10_ValueChanged(object sender, EventArgs e)
        {

        }

        private void numericUpDown21_ValueChanged(object sender, EventArgs e)
        {

        }

        private void numericUpDown11_ValueChanged(object sender, EventArgs e)
        {

        }

        private void numericUpDown16_ValueChanged(object sender, EventArgs e)
        {

        }








    }
}
